﻿using System;
using Validity.Contexts;
using Validity.Localization;
using Validity.Rules;

namespace Validity
{
  public static class MustHaveConstraint
  {
    public static IConditionalValidationContext<TObject, TValue> MustHave<TObject, TValue>(this IValidationContext<TObject, TValue> context, Boolean condition)
    {
      return context.MustHave((obj, val) => condition);
    }

    public static IConditionalValidationContext<TObject, TValue> MustHave<TObject, TValue>(this IValidationContext<TObject, TValue> context, Func<Boolean> predicate)
    {
      Verify.NotNull(predicate);
      return context.MustHave((obj, val) => predicate.Invoke());
    }

    public static IConditionalValidationContext<TObject, TValue> MustHave<TObject, TValue>(this IValidationContext<TObject, TValue> context, Func<TObject, Boolean> predicate)
    {
      Verify.NotNull(predicate);
      return context.MustHave((obj, val) => predicate.Invoke(obj));
    }

    public static IConditionalValidationContext<TObject, TValue> MustHave<TObject, TValue>(this IValidationContext<TObject, TValue> context, Func<TValue, Boolean> predicate)
    {
      Verify.NotNull(predicate);
      return context.MustHave((obj, val) => predicate.Invoke(val));
    }

    public static IConditionalValidationContext<TObject, TValue> MustHave<TObject, TValue>(this IValidationContext<TObject, TValue> context, Func<TObject, TValue, Boolean> predicate)
    {
      Verify.NotNull(predicate);

      context.AddRule(new Rule<TObject, TValue>(
        predicate,
        (obj, val) => String.Format(RuleViolations.General, val)
      ));
      
      return new ConditionalValidationContext<TObject, TValue>(context);
    }
  }
}
